package thinking.in.spring.ioc.bean.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.util.ObjectUtils;
import thinking.in.spring.ioc.container.overview.domain.SuperUser;
import thinking.in.spring.ioc.container.overview.domain.User;
import thinking.in.spring.ioc.container.overview.domain.UserHolder;

public class BeanInstantiationLifecycleDemo
{

    public static void main(String[] args)
    {
        // TODO
        // 加载XML superUser
        // 通过 InstantiationAwareBeanPostProcessor   拦截superUser的创建 返回一个全新的实例

        // 增加一个UserHolder 演示有参构造方法实例化过程 （有参构造方法可以通过autowire来实现）
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        Resource resource = new ClassPathResource("META-INF/dependency-lookup-context.xml");
        EncodedResource encodedResource = new EncodedResource(resource, "utf-8");
        int count = reader.loadBeanDefinitions(encodedResource);
        System.out.println("已加载 BeanDefinition 数量：" + count);
        User user = (User) beanFactory.getBean("user");
        System.out.println(user);
        SuperUser superUser = (SuperUser) beanFactory.getBean("superUser");
        UserHolder userHolder = beanFactory.getBean(UserHolder.class);
        System.out.println(userHolder);
        System.out.println(superUser);
    }

    private static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor
    {

        //superUser 跳过实例化阶段 当然也不会有赋值阶段
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException
        {
            if (beanClass.equals(SuperUser.class) && ObjectUtils.nullSafeEquals(beanName, "superUser"))
            {
                SuperUser superUser = new SuperUser();
                superUser.setName("我是假的CocoAdel");
                return superUser;
            }
            return null;
        }

        //user Bean 跳过bean的赋值
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException
        {
            if (ObjectUtils.nullSafeEquals(beanName, "user"))
            {
                User user = (User) bean;
                user.setName("我是假的Ruby");
                return false;
            }
            return true;
        }


        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException
        {
            if (ObjectUtils.nullSafeEquals(beanName, "userHolder") && UserHolder.class.equals(bean.getClass()))
            {
                MutablePropertyValues propertyValues = new MutablePropertyValues();
                propertyValues.add("num",1);
                return propertyValues;
            }
            return null;
        }
    }
}
